package com.seeyon.apps.bense.bank.manager;

import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.druid.util.StringUtils;
import com.seeyon.apps.bense.bank.core.Constants;
import com.seeyon.apps.bense.bank.core.OpenSDKClient;
import com.seeyon.apps.bense.bank.enums.BankAPIEnum;
import com.seeyon.apps.bense.common.domain.Cap4Update;
import com.seeyon.apps.bense.common.domain.Cap4Where;
import com.seeyon.apps.bense.common.manager.CAP4FormDataManagerExt;
import com.seeyon.apps.bense.util.CAP4FormKit;
import com.seeyon.apps.bense.util.JDBCUtil;
import com.seeyon.apps.collaboration.manager.ColManager;
import com.seeyon.apps.ningbobank.manager.NingBoBankSuperNodeManager;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormDataMasterBean;
import com.seeyon.cap4.form.bean.FormFieldBean;
import com.seeyon.cap4.form.service.CAP4FormManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.constants.ApplicationCategoryEnum;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.manager.AttachmentManager;
import com.seeyon.ctp.common.filemanager.manager.FileManager;
import com.seeyon.ctp.common.po.filemanager.Attachment;
import com.seeyon.ctp.common.po.filemanager.V3XFile;
import com.seeyon.ctp.util.FlipInfo;
import com.seeyon.ctp.util.ParamUtil;
import com.seeyon.ctp.util.UUIDLong;
import com.seeyon.ctp.workflow.supernode.enums.SuperNodeEnums;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;

public class TravelPaymentManagerImpl {

	private static final Logger log = LoggerFactory.getLogger(TravelPaymentManagerImpl.class);

	private static CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");

	private CAP4FormDataManagerExt cap4FormDataManagerExt = (CAP4FormDataManagerExt) AppContext
			.getBean("cap4FormDataManagerExt");

	private static FileManager fileManager = (FileManager) AppContext.getBean("fileManager");

	private static AttachmentManager attachmentManager = (AttachmentManager) AppContext.getBean("attachmentManager");

	private OpenSDKClient openSDKClient = (OpenSDKClient) AppContext.getBean("openSDKClient");

	private ColManager colManager;

	/**
	 * 定时查询付款回执结果接口
	 *
	 * @throws Exception
	 */
	public void doSync() {
		FormBean formBean = null;
		try {
			formBean = cap4FormManager.getFormByFormCode(Constants.travelPaymentTab);
		} catch (BusinessException e) {
			log.error("模板编号: 【{}】 查询表单失败", Constants.travelPaymentTab, e);
		}
		Assert.notNull(formBean, "差旅费报销单未配置模板编号");

		// 根据工号查询底表里是否存在，存在则跳过，否则新增
		FormFieldBean fieldBean = CAP4FormKit.getFieldBean(formBean.getMasterTableBean(), "回执状态");
		Assert.notNull(fieldBean, "表单【{}】,字段【{}】定义不存在", formBean.getFormName(), "回执状态");
		Cap4Where masterWhere = new Cap4Where().eq(fieldBean.getName(), "否");
		int page = 1;
		List<FormDataMasterBean> masterExists = cap4FormDataManagerExt.selectMasterDataList(new FlipInfo(page, 200),
				formBean, null, masterWhere);
		if (CollectionUtil.isEmpty(masterExists)) {
			log.info("***********差旅费报销单【表单编号{}】没有回执状态为否的数据***********", Constants.travelPaymentTab);
			return;
		}
		log.info("差旅报销单不为空=====" + masterExists);
		while (CollectionUtil.isNotEmpty(masterExists)) {
			for (int i = 0, len = masterExists.size(); i < len; i++) {
				FormDataMasterBean formDataMasterBean = masterExists.get(i);
				String billCode = CAP4FormKit.getFieldStrValue(formDataMasterBean, "付款请求号");
				Map<String, Object> paramMap = new HashMap<>();
				paramMap.put("serialNo", billCode);
				Map<String, Object> dataMap = getData(BankAPIEnum.QUERY_SINGLE_TRANSFER_RESULT, paramMap);
				if (!"0000".equals(MapUtil.getStr(dataMap, "retCode"))) {
					continue;
				}
				Map<String, Object> ftlMap = MapUtil.get(dataMap, "transferDtl", Map.class);
				String status = MapUtil.get(ftlMap, "status", String.class); // 获取支付状态 0表示成功
				String errDesc = MapUtil.get(ftlMap, "errDesc", String.class); // 失败信息
				log.info("差旅报销单-errDesc：" + errDesc);
				// 获取summaryId
				String sql = "select * from col_summary where FORM_RECORDID = " + formDataMasterBean.getId();
				List<Map> data = JDBCUtil.doQuery(sql);
				log.info("差旅data=====" + data);
				Long summaryId = 1L;
				if (data.size() > 0) {
					BigDecimal id = (BigDecimal) data.get(0).get("id");
					summaryId = id.longValueExact();
				}
				log.info("summaryId=====" + summaryId);
				if ("0".equals(status)) {
					paramMap.put("queryFlag", "3");
					Map<String, Object> flowMap = getData(BankAPIEnum.QUERY_RECEIPT_LIST_BY_BANKACC, paramMap);
					if (!"0000".equals(MapUtil.getStr(flowMap, "retCode"))) {
						continue;
					}
					String downloadNo = MapUtil.get(flowMap, "downloadNo", String.class);
					if (StrUtil.isBlank(downloadNo)) {
						continue;
					}
					paramMap.put("downloadNo", downloadNo);
					Map<String, Object> downloadMap = getData(BankAPIEnum.GET_ELERECEIPT_DOWNLOAD_URL, paramMap);
					if (!"0000".equals(MapUtil.getStr(downloadMap, "retCode"))) {
						continue;
					}
					List<Map<String, Object>> downloadList = MapUtil.get(downloadMap, "rows", List.class);
					if (CollectionUtil.isEmpty(downloadList)) {
						continue;
					}
					// 判断是否是中国农业银行的自动缴费
					String payBankName = CAP4FormKit.getFieldStrValue(formDataMasterBean, "付款银行名称");
					if ("中国农业银行".equals(payBankName)) {
						// 有两个凭证的时候才会回写
						if (downloadList.size() < 2) {
							continue;
						}
					}
					// 下载地址转为文件流，上传OA 映射到附件
					Long subRef = null;
					try {
						subRef = getReference(downloadList, summaryId);
					} catch (BusinessException e) {
						log.info("上传附件到OA失败");
					}
					Assert.notNull(subRef, "上传文件地址索引不能为空");

					Cap4Where cap4Where = new Cap4Where();
					cap4Where.eq(CAP4FormKit.getFieldBean(formDataMasterBean, "付款请求号").getName(), billCode);
					Cap4Update cap4Update = new Cap4Update();
					FormFieldBean payStatusBean = CAP4FormKit.getFieldBean(formDataMasterBean, "回执状态");
					FormFieldBean tbean = CAP4FormKit.getFieldBean(formDataMasterBean, "附件");
					Assert.notNull(tbean, "表单附件字段未定义");
					cap4Update.add(tbean.getName(), subRef);
					cap4Update.add(payStatusBean.getName(), "0".equals(status) ? "是,交易成功" : "是,交易未知");
					cap4FormDataManagerExt.update(formDataMasterBean.getFormTable(), cap4Update, cap4Where);

					// 超级节点处理
					log.info("formDataMasterBean.getId()===" + formDataMasterBean.getId());
					NingBoBankSuperNodeManager ningBoBankSuperNodeManager = (NingBoBankSuperNodeManager) AppContext
							.getBean("ningBoBankSuperNodeManager");
					Map<String, Object> superNodeDetail = ningBoBankSuperNodeManager
							.getSuperNodeControlDetail(summaryId.toString(), "ningBoBankSuperNodeAction");
					String formRecordId = ParamUtil.getString(superNodeDetail, "formRecordId");
					String superNodeId = ParamUtil.getString(superNodeDetail, "superNodeId");
					log.info("formRecordId===" + formRecordId);
					log.info("superNodeId===" + superNodeId);
					// 成功处理
					if (!StringUtils.isEmpty(formRecordId) && !StringUtils.isEmpty(superNodeId)) {
						ningBoBankSuperNodeManager.operateSuperNode(superNodeId, SuperNodeEnums.RunAction.FORWARD,
								formRecordId, "处理成功");
					}
				} else if ("-2".equals(status) || "-3".equals(status) || "2".equals(status) || "4".equals(status)
						|| "5".equals(status) || "6".equals(status) || "96".equals(status) || "112".equals(status)) {
//					失败：-2 已删除、-3 审批打回交易关闭、2 交易失败、4：交易失败，资金下拨失败、5：联
//					动支付失败，资金退回成功、6：联动支付失败，资金退回查证中、96：联动支付失败，资
//					金退回失败、112：请款失败
					// 超级节点处理
					log.info("超级节点进行失败处理-formDataMasterBean.getId()===" + formDataMasterBean.getId());
					NingBoBankSuperNodeManager ningBoBankSuperNodeManager = (NingBoBankSuperNodeManager) AppContext
							.getBean("ningBoBankSuperNodeManager");
					Map<String, Object> superNodeDetail = ningBoBankSuperNodeManager
							.getSuperNodeControlDetail(summaryId.toString(), "ningBoBankSuperNodeAction");
					String formRecordId = ParamUtil.getString(superNodeDetail, "formRecordId");
					String superNodeId = ParamUtil.getString(superNodeDetail, "superNodeId");
					log.info("超级节点进行失败处理-formRecordId===" + formRecordId);
					log.info("超级节点进行失败处理-superNodeId===" + superNodeId);
					// 失败处理
					if (!StringUtils.isEmpty(formRecordId) && !StringUtils.isEmpty(superNodeId)) {
						ningBoBankSuperNodeManager.operateSuperNode(superNodeId, SuperNodeEnums.RunAction.BACK,
								formRecordId, errDesc);
					}

					Cap4Where cap4Where = new Cap4Where();
					cap4Where.eq(CAP4FormKit.getFieldBean(formDataMasterBean, "付款请求号").getName(), billCode);
					Cap4Update cap4Update = new Cap4Update();
					FormFieldBean payStatusBean = CAP4FormKit.getFieldBean(formDataMasterBean, "回执状态");
					cap4Update.add(payStatusBean.getName(), "");
					cap4FormDataManagerExt.update(formDataMasterBean.getFormTable(), cap4Update, cap4Where);

				} else {
//					中间态：-1 驳回、1 交易待查证、3 待发送、11~94 待审批、95 审批通过、7 暂存、-4 经办
//					撤回、111：请款查证中、113：请款成功，交易待发送、114：联动支付成功，智能支付交
//					易待发送
					log.info("付款还在审批中，不做业务处理");
				}
			}
			masterExists = cap4FormDataManagerExt.selectMasterDataList(new FlipInfo(++page, 200), formBean, null,
					masterWhere);
		}
	}

	private Map<String, Object> getData(BankAPIEnum bankAPIEnum, Map<String, Object> paramMap) {
		Map<String, Object> result = openSDKClient.sendRequest(bankAPIEnum.url(), paramMap);
		Map<String, Object> dataMap = MapUtil.get(result, "Data", Map.class);
		return dataMap;
	}

	private Map<String, Object> getReference(String fileName, String fileUrl, Long masterId, Integer sort)
			throws BusinessException {
		List<Long> fieldIds = new ArrayList<>();
		HttpRequest request = HttpUtil.createGet(fileUrl);
		// 执行请求并获取响应流
		InputStream inputStream = request.execute().bodyStream();
		V3XFile v3XFile = fileManager.save(inputStream, ApplicationCategoryEnum.cap4Form, fileName, new Date(), true);
		Long fieldId = v3XFile.getId();
		fieldIds.add(fieldId);
		long attachmentId = UUIDLong.longUUID();
		Long[] fieldArr = fieldIds.toArray(new Long[] {});
		attachmentManager.create(fieldArr, ApplicationCategoryEnum.cap4Form, masterId, attachmentId);
		List<Long> subReference = new ArrayList<>();
		subReference.add(attachmentId);
		List<Attachment> attachmentList = attachmentManager.getBySubReference(subReference);
		Attachment attachment = attachmentList.get(0);
		Map<String, Object> att = new HashMap<>();
		att.put("subReference", attachmentId);
		att.put("fileUrl", attachment.getFileUrl());
		att.put("sort", sort);
		return att;
	}

	private Long getReference(List<Map<String, Object>> details, Long masterId) throws BusinessException {
		List<Long> fieldIds = new ArrayList<>();
		for (int j = 0; j < details.size(); j++) {
			Map<String, Object> map = details.get(j);
			String fileName = MapUtil.get(map, "voucherNo", String.class) + ".pdf";
			String fileUrl = MapUtil.get(map, "downloadUrl", String.class);
			HttpRequest request = HttpUtil.createGet(fileUrl);
			InputStream inputStream = request.execute().bodyStream();
			V3XFile v3XFile = fileManager.save(inputStream, ApplicationCategoryEnum.cap4Form, fileName, new Date(),
					true);
			Long fieldId = v3XFile.getId();
			fieldIds.add(fieldId);
		}
		Long attachmentId = UUIDLong.longUUID();
		Long[] fieldArr = fieldIds.toArray(new Long[] {});
		String SSCellRange = attachmentManager.create(fieldArr, ApplicationCategoryEnum.cap4Form, masterId,
				attachmentId);
		return attachmentId;
	}
}
